#define WIN32_LEAN_AND_MEAN //just say good bye to mfc...

#pragma comment(lib, "SimpleMathLib.Lib")
#pragma comment(lib, "RenderEngine.lib")

#include <windows.h>
#include <windowsx.h>
#include <tchar.h>

#include "../../SimpleMathLib/Inc/matrix.h"
#include "../../RenderEngine/Inc/RenderConsole.h"
#include "../Inc/InstanceStateMachine.h"

#define   WINDOW_TITLE          __T("BasicWindow")
#define   WINDOW_CLASS_NAME     __T("AppWindow")
#define   WINDOWED_APP          1  //windowed or full screen..

#define   WINDOW_WIDTH          640
#define   WINDOW_HEIGHT         480
#define   WINDOW_BIT            16  // bit depth of a window 8,16,24 etc...

#define   WINDOW_FPS            30   //set fps..

HWND              mainHandle      =   NULL;  //main window handle..
HINSTANCE         appInstance     =   NULL;  //application instance..

DWORD         currentTime  = 0;       //current time..
DWORD         prevTime     = 0;       //prev frame time..
float         deltaTime    = 0;       //delta time..


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT paint;
	switch(msg)
	{
	case WM_PAINT:
		hdc = BeginPaint(hwnd, &paint);

		//place code here..
		//redraw window..

		EndPaint(hwnd, &paint);
		return 0;
		break;
	case WM_DESTROY:
		PostQuitMessage(0);//destroy the window...
		return 0;
		break;
	default:
		break;
	}

	return DefWindowProcW(hwnd, msg, wParam, lParam);//return def window proc..
}

int WINAPI WinMain(HINSTANCE hInstance,
	               HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
				   int nShowCmd)
{
	WNDCLASSEX wc;  //window class..
	MSG msg;   //Used to get message from msg queue..

	wc.cbSize           =      sizeof(WNDCLASSEX);
	wc.cbClsExtra       =      0;
	wc.cbWndExtra       =      0;
	wc.style            =      CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; //set window class styles..
	wc.hbrBackground    =      (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.hCursor          =      LoadCursor(NULL, IDC_ARROW);
	wc.hIcon            =      LoadIcon(NULL, IDI_APPLICATION);
	wc.hIconSm          =      LoadIcon(NULL, IDI_APPLICATION);
	wc.hInstance        =      hInstance;
	wc.lpszClassName    =      WINDOW_CLASS_NAME;  //set window class name..
	wc.lpszMenuName     =      NULL;
	wc.lpfnWndProc      =      WndProc;     //set window call back func...

	if (!RegisterClassEx(&wc)) //register our window class..
	{
		return -1;
	}

	//create our windows here..
	if(!(mainHandle = CreateWindowEx(NULL,  //extra style..
		                         WINDOW_CLASS_NAME, //window class..
								 WINDOW_TITLE, 
								 (WINDOWED_APP ? (WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION) : (WS_POPUP | WS_VISIBLE)),//window styles..
								 0, 0, //window start position..
								 WINDOW_WIDTH, WINDOW_HEIGHT, 
								 NULL, //handler to parent..
								 NULL, //handler to menu..
								 hInstance,  //app instance..
								 NULL  //extral creation param..
								 )))
	{
		return -1;
	}

	appInstance = hInstance; //set app instance.
	if (WINDOWED_APP)
	{
		RECT window_rect = {0, 0, WINDOW_WIDTH - 1, WINDOW_HEIGHT - 1};
		AdjustWindowRectEx(&window_rect,
			               GetWindowStyle(mainHandle), 
						   GetMenu(mainHandle) != NULL,
						   GetWindowExStyle(mainHandle));
		//change window size, make the client rect as large as we defined..
		MoveWindow(mainHandle,  // handle..
			       0, 0,   // start position..
				   window_rect.right - window_rect.left,  //width..
				   window_rect.bottom - window_rect.top,   //height..
				   false ); //repaint
		ShowWindow(mainHandle, SW_SHOW);
	}
	
	if (!RenderConsole::Instance()->InitializeConsole(WINDOW_WIDTH, WINDOW_HEIGHT, mainHandle, WINDOWED_APP))//Init d3d and console window here..
	{
		return -1;
	}

	while(1)
	{
		if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) //get and remove message from queue..
		{
			if (WM_QUIT == msg.message) //app exit..
			{
				break;
			}
			TranslateMessage(&msg);
			DispatchMessageW(&msg); //call callback func...
		}

		currentTime   =   GetTickCount();
		deltaTime = (currentTime - prevTime)/1000.0f;
		if ( deltaTime > (1.0/WINDOW_FPS))
		{
			InstanceStateMachine::Instance()->UpdateStateMachine(deltaTime); //update our application instance here..
			prevTime   =   currentTime;
		}
	}

	return msg.message;
}
